#pragma once
#include <iostream>
#include <string>
#include <functional>

#include <cstring>

#include <pthread.h>
#include <unistd.h>



#include "Sock.hpp"

namespace my_http
{
    using namespace TCP;


    class HttpServer;
    class ThreadData // v3线程创建 线程函数数据
    {
    public:
        ThreadData(std::string ip, uint16_t port, int sockfd, HttpServer *ser)
            : _ip(ip), _port(port), _sockfd(sockfd), _ser(ser)
        {
        }

        std::string _ip;
        uint16_t _port;
        int _sockfd;
        HttpServer *_ser;
    };

    class HttpServer
    {
        using func_t = std::function<std::string(std::string& request)>;
    public:
        HttpServer(func_t func,const uint16_t& port)
            :ss(port)
            ,_func(func)
        {}

        void Init()
        {
            ss.Socket();
            ss.Bind();
            ss.Listen();
        }

        void Start()
        {
            while(true)
            {
                std::string client_ip;
                uint16_t client_port;
                int client_sock = ss.Accept(&client_ip,&client_port);
                while(client_sock < 0)
                {
                    std::cout<<"accept error!"<<std::endl;
                    continue;
                }
                std::cout<<"client accept!"<<std::endl;

                ThreadData* t = new ThreadData(client_ip,client_port,client_sock,this);
                pthread_t tid;
                pthread_create(&tid,nullptr,ThreadFunc,(void*)t);
            }
        }

        // v3-线程 执行函数
         static void *ThreadFunc(void *args)
         {
             pthread_detach(pthread_self()); // 线程分离
             ThreadData *td = static_cast<ThreadData*>(args);
             td->_ser->HttpRequest(td->_ip,td->_port,td->_sockfd);
             close(td->_sockfd);
             delete td;
             return nullptr;
         }

        void HttpRequest(const std::string& client_ip,const uint16_t& client_port,const int& client_sockfd)
        {
            char buf[4096] = {0};
            ssize_t n = recv(client_sockfd,buf,sizeof(buf)-1,0);
            if(n > 0)
            {
                buf[n] = {0};
                std::string package(buf);
                package = _func(package);
                send(client_sockfd,package.c_str(),package.size(),0); //返回给浏览器
            }
            else
            {
                std::cout<<"client[ip:"<<client_ip<<"|port:"<<client_port<<"]:quit!"<<std::endl;
            }
        }

    private:
        SockServer ss;
        func_t _func;
    };
}